MOTHER MUSIC FORMAT v1.0 By Justin Olbrantz (Quantam) The permanent home of this specification and others, with the latest updates, is https://github.com/TheRealQuantam/RetroDocs. The Mother sound engine is the final version of the Hirokazu Tanaka engine which was derived from the Yukio Kaneoka engine dating all the way back to Nintendo's earliest NES games by Research and Development 1. An earlier version of the Tanaka engine would be used for the well-known Metroid and Kid Icarus, and the Mother engine would take Tanaka and R&D1 through the end of the NES era. Apart from Mother, other hit games to use the Mother engine include Dr. Mario and the legendary Tetris. The Tanaka-Kaneoka engines show a clear progression of features culminating in the Mother engine. Most of the awful inflexibility of the Metroid engine previously documented is gone, with new music data-based mechanisms for timbre, tempo, and looping control. The engine appears to take some inspiration from the R&D4 engines such as that of Super Mario Bros. 3, adopting a per-channel version of their block/playlist structure. While the Metroid engine was decidedly a hybrid system, mixing music data with hard-coding, only 1 (new) part of the Mother engine is a hybrid: the pitch envelope system. Overall the engine is vastly more flexible than the Metroid engine and highly efficient at eliminating redundancy in music data, but the block system makes the engine vastly more complicated to compose for. Basic Features: - Single byte notes and rests, though current note length must be previously defined with an additional byte + Hybrid tempo system that mimics staff notation divisive rhythm - 5-octave chromatic scale from A1 (55 Hz) to E7 (2637 Hz) for square wave (game-specific); triangle is 1 octave lower. - 9 note lengths from whole notes through 16th notes with dots and triplets for some lengths for all tempos, plus several tempo-specific lengths (game-specific) - 8 tempos from 82 to 225 BPM (game-specific) - 5 channels - square 1, square 2, triangle, noise, DMC - with 4 separate event sequences (DMC events are encoded on the noise channel) + Multi-timbre support - Square channels: duty cycle, channel volume or non-looping volume envelopes, looping pitch envelopes - Triangle channel: looping pitch envelopes - Global set of 10 noise presets (game-specific) - Global set of 2 DMC presets (game-specific) - Single-level unnested loops - Per-channel block structure allow reuse of data as well as more than 256 bytes per channel - Global transpose setting Major Differences with the Metroid Engine: - Timbre, global tempo, and triangle auto-release now controllable by music data - Support for DMC sounds - New volume envelope format that is half the size but doesn't allow modification of duty cycle - Pitch envelopes - Global transpose setting settable by music data - Track looping is now per-channel and no longer limited to whole track looping - Per-channel block structure allows reuse of data as well as more than 256 bytes per channel Some general notes in interpreting this specification: - All word (16-bit) values in the format are little-endian, with the least-significant byte preceding the most-significant, unless noted otherwise. - All values are unsigned unless noted otherwise. - All numbers preceded by $ are hex, and in general unless they represent byte strings or addresses most numbers without $ are in decimal. - Byte values are generally shown as hex "ab" where "a" is the high nibble and "b" is the low nibble (standard mathematical digit ordering). However, when it is necessary to show bit fields, bytes are shown in binary as "abcd efgh" (mathematical order); in bit fields "-" means that the value of the bit does not matter in the given context. - Many command lists (e.g. channel data commands) are encoded ambiguously, where 1 value could be interpreted as multiple different commands (e.g. 00 could match 0n). These lists are ordered such that the first matching command is the correct interpretation. Track Structure At the highest level Mother's track structure is almost identical to Metroid's: a table of offsets into blocks containing the headers for each track; however, the headers contain less metadata and the metadata they do contain (such as tempo and transpose) are now merely the initial values, and may be changed by music data during play. However, due to the amount of music in an RPG like Mother and the self-imposed limitation of 256 byte-large blocks containing track headers, Mother has 2 banks of music, 1 for "low" tracks 1-$18 and the other for "high" tracks $19-$31; it is worth noting that these banks are nearly packed to the gills, with the maximum of $19 tracks per bank being possible with the 256-byte limit. What is VERY different, however, is what the header's channel data addresses point to. Rather than pointing to the actual music data as in Metroid, they point to a playlist of blocks for the channel. This is an array of 16-bit words that specify the addresses of blocks of music data and in which order they should be played, terminated either by an end of track code or a goto code that specifies the channel should continue from a specified location in the playlist. The playlist performs the function of (infinitely) looping the track (though note that some tracks loop on some channels but eventually end the track on another), reusing blocks of music data like "subroutines" in other engines, and freeing the engine from the Metroid engine's limitation of 256-byte channel data (now each block is limited to 256 bytes); they may even be used for example to have square 1 and square 2 play the same sequence of notes with a delay on 1 channel or different timbre by having different first blocks that then both jump to the same playlist location. And while it is not recommendable to perform local loops with the playlist as channel music data loops are more efficient for that purpose, the playlist may be used to add additional levels of looping to a track. Accordingly, the "end of track" 0 command in music data now means "end of block", and the "end of track" command is performed by the playlist. This means that most blocks on all channels will be terminated, however it is still possible for the final blocks of some channels to be unterminated because another channel will end the track before erroneous data is played. Bank configuration: $8000-$9fff: Bank $1c $a000-$bfff: Bank $1d 1c:903e byte[$18]: Low track header offset table 1c:9056 byte[$19]: High track header offset table 1c:906f struct[$18]: Low track header block 1c:915f struct[$19]: High track header block Track Header Format: +0 byte: Initial global transpose in modified sign-magnitude format with the format nmmm mmmm. If n is clear the transpose value = +m; if n is set the transpose value = -1 - m. The transpose value must be an even number, as it is 2x the number of semitones and fractional semitones are not supported. +1 byte: Initial note length table offset (implicitly, tempo). See Time and Tempo for a list of possible values. +2 word[4]: Channel playlist addresses in order of square 1, square 2, triangle, and noise, or a high byte of $ff (canonically $ffff) if none. Example 81 0C 8F 99 97 99 9F 99 A7 99 81: Initial global transpose n = 1: Negative m = 1: With n = 1 the transpose value = -1 - 1 = -2 (-1 semitone) 0C: Initial note length table offset t = $c: Table offset $c: 180 BPM 8F 99: Square 1 channel playlist address $998f 97 99: Square 2 channel playlist address $9997 9F 99: Triangle 1 channel playlist address $999f A7 99: Noise channel playlist address $99a7 Block Playlist Format (word values, shown in mathematical order, not their physical little-endian byte order): 00--: Global end of track. All channels stop when this is encountered on any channel. ff-- AAAA: Goto. Set the current playlist location address (not block address) to A. AAAA: Play the block of music data at address A. Examples Square 1 channel: 62 99 00 00 62 99: Play block address $9962 00 00: End of track Square 2 channel of SAME track: 71 99 71 99: Play block address $9971 Note that there is NO termination for this channel, as the track will be terminated by the end of track command on square 1. Square 1 playlist at $b0f8: 0C B1 15 B1 FF FF 02 B1 0C B1: Play block address $b10c 15 B1: Play block address $b115 FF FF 02 B1: Go to playlist address $b102 Square 2 playlist at $b100 of same track: 12 B1 1F B1 FF FF 02 B1 12 B1: Play block address $b112 1F B1: Play block address $b11f FF FF 02 B1: Go to playlist address $b102. This looks familiar. Triangle playlist of same track: 2F B1 00 00 2F B1: Play block address $b12f 00 00: End of track Note 2 things here. $b102 is the second entry in the square 2 playlist (block $b11f); in other words, the square channels have a couple initial unique blocks before merging to the same data (square 1 is delayed by 26 frames, among other things). Second, triangle block $b12f is much longer than any of the square channel blocks (16 seconds per loop), so the square channels loop repeatedly until the triangle channel terminates the track at 8:33. The irony of this is that in fact the triangle channel IS looping (32 loops of 16 sec), but it's looping using the music data loop construct within the block; it is not at all clear why it was not simply made to loop infinitely like the rest. Time and Tempo The note length system in Mother is identical to that in Metroid, save that music data may change the table offset during play. Note/rest durations are frame-based, and a master table specifies note durations in frames. At any given point the track has a $10-element window into this table for use by all channels, and set note length commands select 1 of these lengths. This table is arranged (and used in game music) to provide 8 different tempos with a common set of 9 musical lengths with common indices; various other lengths are available based on the window used for the track, but they are not common between tempos. The master table giving lengths in frames is: 0 : 4 8 16 32 64 24 48 12 10 5 2 1 5 10 20 40 10: 80 30 60 15 12 6 3 2 6 12 24 48 96 36 72 18 20: 16 8 3 1 4 2 0 144 7 14 28 56 112 42 84 21 30: 18 9 3 1 2 8 16 32 64 128 48 96 24 21 10 4 40: 1 2 192 9 18 36 72 144 54 108 27 24 10 20 40 80 50: 160 60 120 30 26 13 5 1 2 23 11 22 44 88 176 66 60: 132 33 29 14 5 1 2 23 When arranged by the base offsets used by the game the table looks like this: 0 1 2 3 4 5 6 7 8 9 a b c d e f BPM 16 8 4 2 1 4D 2D 8D 4T 8T 32 0 (225): 4 8 16 32 64 24 48 12 10* 5* 2 1 c (180): 5 10 20 40 80 30 60 15 12* 6* 3* 2 18 (150): 6 12 24 48 96 36 72 18 16 8 3 1 4 2 0 144 28 (129): 7 14 28 56 112 42 84 21 18* 9* 3* 1 2 35 (113): 8 16 32 64 128 48 96 24 21* 10* 4 1 2 192 43 (100): 9 18 36 72 144 54 108 27 24 * * 4c (90): 10 20 40 80 160 60 120 30 26* 13* 5 1 2 23 5a (82): 11 22 44 88 176 66 132 33 29* 14* 5* 1 2 23 Using these windows, the following standard length codes are defined: Whole Half 4th 8th 16th 32nd Normal: 4 3 2 1 0 a* Dotted: 6 5 7 Triplet: 8* 9* * Triplets and 32nds in some tempos are not whole numbers of frames, and will not properly mix with other lengths. These can either be avoided in those tempos or worked around by varying the lengths of notes of that type by 1 frame or inserting short (e.g. 1 frame) rests so that 3 triplets or 2 32nds add up to the correct whole number of frames. Note critically that all lengths beyond quarter triplet are MISSING for 100 BPM. Notes on the triangle wave channel are capable of auto-release prior to the end of the specified note duration. Depending on the current auto-release settings specified by the set timbre command on the triangle channel, notes may be set to either never auto-release, auto-release after a fixed number of frames (up to 8), or dynamic auto-release of notes 1 frame before the end of the note or after 15 frames, whichever is sooner. Notes and Rests The Mother engine uses 3 different key sets: 1 for melodic channels (though note that triangle is 1 octave lower than square channels) and 2 for the noise channel (1 for noise presets and 1 for DMC presets). 1 oddity of the Tanaka-Kaneoka engines is that rather than keys being numbered sequentially, key values for everything except DMC presets are actually byte offsets into various lookup tables (this made somewhat more sense for the Kaneoka engine and Kondo engine derived from it). For melodic keys that table is the pitch period table which has word-sized elements, resulting in all valid key values being even. For these keys it's easiest to pretend that the bottom bit is not part of the key value and must simply be 0, but the transpose feature added in the Mother engine exposes this detail as the transpose value is added directly to the key value to get the byte offset into the array. While not at all recommendable, it's possible to have both key values and transpose values be odd to produce an even sum that will correctly reference a key pitch. For this document we will pretend that melodic key numbers exclude the bottom bit, though there is 1 place where the truth of the matter can't be hidden. The melodic key set has a nominal base key of A#1 for all known games, though for unknown and possibly historical reasons its key 0 is A1 and key 1 is rest. While the engine is capable of using key numbers 2-$4d and $50-$57 (additional ranges with an exploit), no known game uses the entire available range. Mother's Key Table: Oct C C# D D# E F F# G G# A A# B Max Detune at B 1: 0* 0.96 cents 2: 2 3 4 5 6 7 8 9 a b c d 1.91 cents 3: e f 10 11 12 13 14 15 16 17 18 19 3.83 cents 4: 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 7.69 cents 5: 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 15.49 cents 6: 32 33 34 35 36 37 38 39 3a 3b 3c 3d 31.41 cents 7: 3e 3f 40 41 42 * Key code 0 is an exploit: if key code 0 IMMEDIATELY follows a set length command it will be assumed to be a note/rest rather than being interpreted as an end of block command. While not relevant to any known game, this same exploit can be used with keys $4e-$4f and above $57. Like the true way melodic keys work, noise codes are indices into an array of noise presets, though here they are 1-based offsets into entries of 3 bytes. Rest is code 1, and some games like Mother exploit the fact that only the first byte of the 3 is necessary to silence the channel to place the first preset at 2. All together, Mother supports the following presets: 2, 4, 7, $a, $d, $10, $13, $16, $19, $1c. Finally there are the DMC presets. Each byte-sized key/rest command on the noise channel is actually 2 commands in 1: the low bits contain a noise preset code and the high bits contain a DMC preset code. There are actually 2 variants of the Mother engine, depending on whether 2 bits or 3 are dedicated to the DMC code. Mother uses 2 bits and is limited to 3 DMC presets, although it only uses 2. In both versions of the engine DMC key code 0, as well as any other unused codes, is rest for the DMC channel. DMC Presets: 1: Kick/bass drum 2: Snare drum Channel Data 1 major difference between the Tanaka-Kaneoka engines and non-Nintendo engines is that while each channel has separate music data, the end of track command (part of the playlist, in the Mother engine) applies globally, and all channels are affected when ANY channel encounters it. Because of this, it is not necessary to explicitly terminate all channels for tracks that do not loop, only the 1 that will reach its end first. Unlike the Metroid engine, however, all channels must be made to loop for looping tracks. Channel Data Format: 00: End of block. Advance to the next entry in the channel's playlist. 9c nmmm mmmm: Set global transpose. If n is clear the transpose value = +m; if n is set the transpose value = -1 - m. The transpose value must be an even number, as it is 2x the number of semitones and fractional semitones are not supported. 9e tt: Set global note length table offset (implicitly, tempo) to t ff: End loop. If loop counter is not 0 decrement and loop, else continue. MUST be in the same block as its start loop command. bL: Set current channel note length code to L. For triangle set linear counter according to current triangle auto-release settings. Must be IMMEDIATELY followed by a note/rest. cL (11nn nnnn): Begin loop and set number of times to play loop to n (1-$3e or 0 is interpreted as $100) Melodic Channels Only: 9f pppx xxxx CC: Set channel timbre. MUST NOT be used on noise channel. Set pitch envelope to p (0 if none) and base ctrl 1 value to C. For square channels: Set volume envelope to x (0 if none), and C has the form ddLV vvvv: d: Duty cycle: 12.5% (0), 25% (1), 50% (2), or 75% (3) L: Disable length counter and play forever. Should always be set, as the engine does not provide any control over the length counter. V: If set v is the channel volume, else v is the volume decay speed. Should always be set. v: Channel volume 0-$f. For triangle channel: p (in addition to setting the pitch envelope), x, and C control auto-release in a way that seems contradictory and will be clarified later in this section. C has the form Fnnn nnnn: F: If set disables auto-release if n is non-0. If clear, apply n. n: The number of quarter-frames to play notes before auto-release. p and x set the auto-release settings: x != 0: Set auto-release time to x quarter-frames p is 0-1 or 6-7: Set dynamic auto-release p is 2-5: Disable auto-release 02: Rest for current note length. Acts as a rest if EITHER the unmodified byte OR byte + transpose value is 02. E.g. the command 9C 83 would set a transpose value of -2 semitones, and a 06 "note" would then resolve to a rest (6 - 4 = 2). kkkk kkk0: Play key k + transpose value/2 for current note length. This sum cannot be 1. Noise Channel Only: DDpp pppp: Perform noise channel command p and DMC channel command D for current note length Noise channel: p = 1: Noise channel rests p > 1: Play noise preset p DMC channel: D = 1-2: Play DMC preset D Else: DMC channel rests As previously stated, any byte immediately following a set length command is interpreted as a note/rest, allowing access to keys with the same values as other commands; however, as no known game uses keys outside the normally accessible range, this only (additionally) allows access to key code 0. Some notes on the set timbre command are in order. The ctrl 1 register ($4000, $4004, etc.) value specified is the base value for the channel, and can be modified in a couple ways. For square wave channels, if the channel uses a volume envelope the bottom 4 bits of this value (the volume field) will be replaced by the current volume from the envelope. However the initially specified volume is retained, and will be restored if the envelope ends by restoring the base volume. On the triangle channel the ctrl 1 register controls auto-release at the hardware level, and the set note length and set timbre commands fight over what is written to this register. The set timbre command sets the auto-release settings and ctrl 1 value as specified; the set note length command sets ctrl 1 BASED ON the current auto-release settings. The outcome will be different depending on the order of commands. If the set timbre command comes last, auto-release will be directly controlled by the ctrl 1 value specified, and the auto-release settings specified won't take effect until the next set note length command. If the set note length command comes last, the ctrl 1 value specified in the set timbre command will be completely overwritten based on the auto-release settings. Examples Square channel (current note length base offset is +4c: 90 BPM): 9F B3 31: Set timbre: envelopes and base ctrl 1 p = 5: Pitch envelope 5 x = $13: Volume envelope $13 d = 0: Duty cycle 0 (12.5%) L = 1: Disable length counter V = 1: v is volume v = 1: Base volume 1. Will not actually be used as volume envelope $13 does not restore base volume. D2: Begin loop n = $12: Play loop $12 times B2: Set note length L = 2: Quarter note (40 frames) 1A x3: Notes k = $d: Key B2 B1: Set note length L = 1: 8th note (20 frames) 1A: Note k = $d: Key B2 1C: Note k = $e: Key C3 FF: End loop Triangle channel of same track: 9F A0 00: Set timbre: pitch envelope, auto-release settings, and base ctrl 1 1:x = 0: No explicit auto-release length 1:p = 5: Pitch envelope 5. Auto-release disabled. 2:F, 2:n: Ignored since set note length is done before notes are played B7: Set note length. Also overwrites F and n from previous command with auto-release settings from p and x: disable auto-release. L = 7: Dotted 8th note (30 frames) 24: Note k = $12: Key E2 (triangle is 1 octave lower) B0: Set note length L = 0: 16th note (10 frames) 02: Rest Noise channel of same track: D4: Begin loop n = $14: Play loop $14 times B2: Set note length L = 2: Quarter note (40 frames) 41: Note event D = 1: Play DMC preset 1 (kick drum) n = 1: Noise channel rests 44: Note event D = 1: Play DMC preset 1 n = 4: Play noise preset 4 41: Note event D = 1: Play DMC preset 1 n = 1: Noise channel rests 07: Note event D = 0: DMC channel rests n = 7: Play noise preset 7 FF: End of loop Square channel: 9C 8D: Set global transpose n = 1: Negative m = $d: Transpose value = -1 - $d = -$e (-7 semitones) 00: End of block Triangle channel: 9F 0A 00: Set timbre: pitch envelope, auto-release settings, and base ctrl 1 1:x = $a: Set duration until auto-release to $a quarter-frames 1:p = 0: No pitch envelope 2:F, 2:n: Ignored since set note length is done before notes are played B3: Set note length L = 3: Half note (56 frames at current tempo). Notes will auto-release after 10 quarter-frames. ... 9F 00 00: Set timbre: pitch envelope, auto-release settings, and base ctrl 1 1:x = 0: No explicit auto-release length 1:p = 0: No pitch envelope. Do NOT disable auto-release; result: dynamic auto-release. 2:F, 2:n: Ignored since set note length is done before notes are played B3: Set note length L = 3: Half note (48 frames). Notes will auto-release after 15 frames. ... B1: Set note length L = 1: 8th note (12 frames). Notes will auto-release after 11 frames. Timbre and Envelopes Depending on the channel, up to 3 types of timbre control exist in the Mother engine: the ctrl 1 register (especially the duty cycle for square wave channels), volume envelopes, and pitch envelopes, all of which are set by the set timbre command. Volume envelopes in the Mother engine are fairly short non-looping sequences of volume values that end either by restoring the base volume for the channel or silencing the channel. To reduce the space required, the Mother engine packs 2 volume values into each byte of the envelope. The engine theoretically supports up to $1f volume envelopes, but Mother has $1b envelopes. Examples A8 76 FF: Short decay envelope into sustain. Frames 0-3 will have the volume values $a, 8, 7, 6, then the channel base volume will be used. 91 91 91 91 91 91 91 91 91 91 F0: Odd short, non-sustaining, 30 Hz tremolo envelope of center 5 and depth (center to peak) 4 that silences the channel after 20 frames (1/3 sec). 30 Hz is above the limit of hearing, so this will likely have a peculiar frequency modulation effect. Pitch envelopes are the only truly janky feature of the Mother engine. They are a hybrid system that mixes period-linear absolute (i.e. not relative to the previous frame) period offset arrays with hard-coded behavior (including the length and loop points of the arrays). Making matters worse is the fact that on the triangle channel the "forever" field of the auto-release settings is encoded in the same bits as the pitch envelope number, meaning only certain envelope/auto-release setting combinations are possible. While it is entirely conceivable that the set of envelopes could be game-specific, all games I've investigated have had the same set of pitch envelopes. A basic description of the pitch envelopes is as follows, showing the envelope number, "forever" field, and a basic description; for a more detailed description see the additional information section. E F Description 1: 0 6 Hz vibrato with depth (center to peak) of 2 period units 2: 1 Slides period from 0 to -10 over $10 frames, performs 15 Hz depth 1 vibrato for 2 cycles, then sustains a constant -10 period offset 3: 1 Fixed -2 period offset 4: 1 Pitch slide from +9 to 0 period offset followed by 6 Hz depth 1.5 vibrato. Is NOT applied to key $23. 5: 1 6 Hz depth 2 vibrato that has a fade-in period of $21 frames 6: 0 Pitch slide from +9 to 0 period offset followed by 6 Hz depth 1.5 vibrato. Is NOT applied to key $23. 7: 0 6 Hz depth 2 vibrato Additional Tables and Information Track Table Track bank 0: Header offset table 903e, header block base 906f: 1 Eight Melodies @906f: +24 +18 ffff ffff 76c ffff Triangle @ 76c: 92aa 92b1 92bc 92c7 92d3 92df 92e8 92f5 9301 0000 2 Battle Theme 1 @9079: +0 +28 9309 9311 931b 932d Square 1 @9309: 9592 | 9335 Square 2 @9311: 95a4 | 940b 944e Triangle @931b: 95b6 | 94e7 94f9 94e7 94e7 94f9 952a Noise @932d: 95c8 | 9543 3 Battle Theme 2 @9083: +0 +28 956e 9578 9582 958a Square 1 @956e: 9592 | 95cb 960d Square 2 @9578: 95a4 | 95ec 96b1 Triangle @9582: 95b6 | 971f Noise @958a: 95c8 | 977a 4 Battle Theme 3 @908d: +0 +28 979e 97a8 97b2 97be Square 1 @979e: 9592 | 97c8 9800 Square 2 @97a8: 95a4 | 9814 9895 Triangle @97b2: 95b6 | 98df 98fe 98f3 Noise @97be: 95c8 | 992b 992b 5 Victory @9097: +0 +0 995a 995e 9960 ffff Square 1 @995a: 9962 0000 Square 2 @995e: 9971 Triangle @9960: 9980 6 Pollyanna (I Believe in You) @90ab: +0 +35 9b0e 9b18 9b22 9b2a Square 1 @9b0e: 9b32 | 9bab 9bef Square 2 @9b18: 9b53 | 9c96 9ccd Triangle @9b22: 9b74 | 9d05 Noise @9b2a: 9b8c | 9c3f 7 Bein' Friends @90a1: +0 +28 9d84 9d90 9d9c 9da8 Square 1 @9d84: | 9db4 9e29 9e29 9ec2 Square 2 @9d90: | 9ddb 9e4e 9e4e 9f17 Triangle @9d9c: | 9e07 9e72 9e72 9f5a Noise @9da8: | 9e15 9eae 9eae 9fab 8 Advent Desert @90b5: -2 +c 998f 9997 999f 99a7 Square 1 @998f: 99af | 99cb Square 2 @9997: 99b8 | 9a3d Triangle @999f: 99c1 | 9aea Noise @99a7: 99c7 | 9b03 9 Magicant @90bf: +0 +4c a083 a08b a091 a09f Square 1 @a083: a0a5 | a0af Square 2 @a08b: | a0ac Triangle @a091: | a11b a127 a138 a138 a149 Noise @a09f: | a161 a Snow Man @90c9: +0 +35 a171 a187 a18d ffff Square 1 @a171: a1fd | a207 a22c a207 a254 a272 a28c a272 a2a0 Square 2 @a187: a203 ffff a173 Square 2 @a173: | a207 a22c a207 a254 a272 a28c a272 a2a0 Triangle @a18d: | a197 a197 a1d0 b Mount Itoi @90d3: +0 +4c a2c4 a2ca a2d0 a2d6 Square 1 @a2c4: | a2dc Square 2 @a2ca: | a2f6 Triangle @a2d0: | a33f Noise @a2d6: | a36d c Factory @90dd: +0 +35 a68e a686 a698 a6a0 Square 1 @a68e: a707 | a6b1 a6f4 Square 2 @a686: | a6ae a6f1 Triangle @a698: | a70d a716 Noise @a6a0: | a72a a73d a74f a73d a755 d South Cemetery @90e7: +0 +35 a37c a384 a38c a394 Square 1 @a37c: a39c | a3fd Square 2 @a384: a3b4 | a3fa Triangle @a38c: a3cf | a443 Noise @a394: a3e2 | a46d e Twinkle Elementary School @90f1: +0 +18 a480 a486 a48c a492 Square 1 @a480: | a498 Square 2 @a486: | a4dc Triangle @a48c: | a508 Noise @a492: | a52e f Humoresque of a Little Dog @90fb: +0 +18 a565 a56d a573 a579 Square 1 @a565: a621 | a582 Square 2 @a56d: | a57f Triangle @a573: | a627 Noise @a579: | a65f 10 Poltergeist @9105: -8 +18 9fda 9fe4 9fee 9ff8 Square 1 @9fda: a000 | a005 a01b Square 2 @9fe4: a023 | a023 a03e Triangle @9fee: a046 | a051 a05f Noise @9ff8: a068 | ad5d 11 Basement @910f: +0 +28 a768 a770 a77c a784 Square 1 @a768: a78c | a7b1 Square 2 @a770: a797 | a7be a7b4 a7e1 Triangle @a77c: a7a2 | a7ec Noise @a784: a7ac | a803 12 My Home @9119: +2 +43 a8ec a8e6 a8f2 a8f8 Square 1 @a8ec: | a939 Square 2 @a8e6: | a903 Triangle @a8f2: | a959 Noise @a8f8: | a8fe 13 Cave 2 @9123: +0 +35 a973 a97d a985 a98d Square 1 @a973: a9b1 aa0a | aa12 Square 2 @a97d: a995 | a9ef Triangle @a985: a9ca | aa2a Noise @a98d: a9e2 | aa4c 14 The Paradise Line @912d: +0 +18 bb4f bb63 bb6f bb83 Square 1 @bb4f: bb8b | bc34 bc34 bc48 bc34 bc34 bc48 bc5b Square 2 @bb63: bbb8 | bca5 bca5 bd03 Triangle @bb6f: bbd9 | bd4d bd4d bd5b bd4d bd4d bd5b bd65 Noise @bb83: bc06 | bd86 15 Fallin' Love @9137: +0 +43 aa75 aa83 aa8d aa93 Square 1 @aa75: | aabd aac5 aac1 aac5 aaa7 Square 2 @aa83: aa99 | aa9d aad4 Triangle @aa8d: | ab0c Noise @aa93: | ab1b 16 Mother Earth @9141: +0 +28 ba33 ba2d ba39 ba3f Square 1 @ba33: | ba9c Square 2 @ba2d: | ba45 Triangle @ba39: | bb17 Noise @ba3f: | bb49 17 Tank @914b: +0 +18 ab37 ab47 ab55 ab5d Square 1 @ab37: | abce abd6 abd6 abe8 ac43 ab7a Square 2 @ab47: | ac0a ac12 ac12 ac24 ab65 Triangle @ab55: | acf3 ab95 Noise @ab5d: | ad3d abb2 18 Ruins of Desert @9155: +0 +c a80c a814 a81a ffff Square 1 @a80c: | a820 a827 Square 2 @a814: | a824 Triangle @a81a: | a892 Track bank 1: Header offset table 9056, header block base 915f: 19 Queen Mary's Song @915f: +0 +28 addb adc3 ffff ffff Square 1 @addb: ade5 ffff adc5 Square 1 @adc5: | 92b1 92bc 92c7 92d3 92df 92e8 92f5 9301 ade1 Square 2 @adc3: adeb | 92b1 92bc 92c7 92d3 92df 92e8 92f5 9301 ade1 1a Wisdom of the World @9169: +0 +5a ae52 ae58 ae5e ffff Square 1 @ae52: | ae64 Square 2 @ae58: | aec0 Triangle @ae5e: | af21 1b Tombstone @9173: +24 +4c b0e5 b0dd ffff ffff Square 1 @b0e5: b0f1 | 9c99 Square 2 @b0dd: | b0ed 9c99 1c Game Over @917d: +0 +4c b0f8 b100 b108 ffff Square 1 @b0f8: b10c b115 ffff b102 Square 1 @b102: | b11f Square 2 @b100: b112 | b11f Triangle @b108: b12f 0000 1d Big Victory @9187: +0 +18 b147 b14b b14d ffff Square 1 @b147: b14f 0000 Square 2 @b14b: b161 Triangle @b14d: b175 1e Airplane @9191: +0 +18 af4e af54 af5a af6c Square 1 @af4e: | af72 Square 2 @af54: | afb2 Triangle @af5a: | affd b02e b02e b09d b0ba b09d b0c4 Noise @af6c: | b03d 1f Level Up @919b: +6 +0 ae1e ae28 ae30 ffff Square 1 @ae1e: b14f ae38 | ae43 Square 2 @ae28: b161 | ae40 Triangle @ae30: b175 | ae4f 20 Recovery @91a5: -4 +18 adef adf3 adf5 ffff Square 1 @adef: adf7 0000 Square 2 @adf3: ae04 Triangle @adf5: ae10 21 Fanfare @91af: -4 +43 b51e b522 b524 ffff Square 1 @b51e: b532 0000 Square 2 @b522: b526 Triangle @b524: b53f 22 Live House @91b9: -8 +18 b184 b18a b196 b1a2 Square 1 @b184: | b1a8 Square 2 @b18a: | b1c4 b1c4 b1da b1c4 Triangle @b196: | b1ed b1ed b201 b1ed Noise @b1a2: | b212 23 All That I Needed (Was You) @91c3: +0 +18 b222 b238 b248 b25a Square 1 @b222: b2c5 b2d9 b2d9 b31e b329 b329 b329 b34e b2d9 b31e b25e b2ae Square 2 @b238: b2ae b37b b3b5 b37b b3b8 b37b b272 0000 Triangle @b248: b2d1 b426 b426 b443 b446 b446 b453 b426 b29b Noise @b25a: b46a b491 24 Melody 1 - Doll @91cd: +48 +28 9259 925d ffff ffff Square 1 @9259: 929e 92b1 Square 2 @925d: 92ae 0000 25 Melody 2 - Canary @91d7: +24 +28 9261 9265 ffff ffff Square 1 @9261: 92a4 92bc Square 2 @9265: 92b9 0000 26 Melody 3 - Monkey @91e1: +0 +28 9269 926d ffff ffff Square 1 @9269: 92a4 92c7 Square 2 @926d: 92c4 0000 27 Melody 4 - Piano @91eb: +0 +28 9271 9275 ffff ffff Square 1 @9271: 929e 92d3 Square 2 @9275: 92d0 0000 28 Melody 5 - Cactus @91f5: +48 +28 9279 927d ffff ffff Square 1 @9279: 92a4 92df Square 2 @927d: 92dc 0000 29 Melody 6 - Dragon @91ff: +24 +28 9281 9285 ffff ffff Square 1 @9281: 92a4 92e8 Square 2 @9285: 92e5 0000 2a Melody 7 - EVE @9209: +48 +28 9289 928d ffff ffff Square 1 @9289: 929e 92f5 Square 2 @928d: 92f2 0000 2b Melody 8 - Tombstone @9213: +24 +28 9291 9295 ffff ffff Square 1 @9291: 92a4 9301 Square 2 @9295: 92fe 0000 2c Giegue @921d: +0 +43 b547 b54d ffff ffff Square 1 @b547: | b553 Square 2 @b54d: | b559 2d Ending @9227: +0 +28 b8c0 b8b2 b8d4 b8e2 Square 1 @b8c0: b6df b931 b67c b781 b7c7 b825 b69d | b6df Square 2 @b8b2: b6a0 b8f0 b666 b72e | b6a0 Triangle @b8d4: b724 b9ff b693 b83b | b724 Noise @b8e2: b729 ba23 b698 b882 | b729 2e Choucream Zoo @9231: +0 +28 b55f b565 a77e a786 Square 1 @b55f: | b56b Square 2 @b565: | b573 Triangle @a77e: | a7ec Noise @a786: | a803 2f Phone @923b: +0 +18 ffff b57b ffff ffff Square 2 @b57b: | b581 30 Youngtown @9245: +0 +28 b589 b58f b595 ffff Square 1 @b589: | b5a1 Square 2 @b58f: | b5cd Triangle @b595: | b602 31 Cave 1 @924f: +0 +28 b63c b644 ffff ffff Square 1 @b63c: b64a | b653 Square 2 @b644: | b650 Reading the table: 31 Cave 1 @924f: +0 +28 b63c b644 ffff ffff - Track number $31. Note that this is the number used to play the track in game. To get the track's index in the bank header offset arrays, subtrack 1 or $19 from tracks in the 2 banks. Thus this is $31 - $19 = index $18 in the bank 1 header offset array. - Track name "Cave 1" - Track header address $924f - +0 initial transpose value in decimal (+0/2 = +0 semitones) - Initial note length table base offset $28 (~129 BPM) - Square 1 playlist address $b63c, square 2 $b644 - No triangle or noise channel data for this track Square 1 @b63c: b64a | b653 - Square 1 playlist starting at address $b63c - Plays block $b64a, then repeatedly plays block $b653. The playlist is terminated by ffff b63e which loops as shown, but this is hidden to make the playlist more readable. Square 1 @9291: 92a4 9301 Square 2 @9295: 92fe 0000 - Square 2 channel terminates the track with an end of track command - Square 1 is terminated implicitly by square 2, and has no terminator of its own Square 2 @a187: a203 ffff a173 Square 2 @a173: | a207 a22c a207 a254 a272 a28c a272 a2a0 - Square 2 channel has 2 playlist segments due to a goto command - The goto is not hidden because it does not loop but goes to a different playlist segment. The second playlist segment does loop so its terminator is hidden. 1 Eight Melodies @906f: +24 +18 ffff ffff 76c ffff Triangle @ 76c: 92aa 92b1 92bc 92c7 92d3 92df 92e8 92f5 9301 0000 Track 1 is very special. Its triangle channel points into RAM, as the playlist is constructed dynamically. This is the Eight Melodies track, and it is made up of 8 pieces of the melody (the inner 8 blocks). Depending on whether a piece has been picked up in game, the block will either be as shown here or a placeholder beep. The base (no pieces acquired) version of this track is copied from 1c:8217 ($a words) during initialization. Game-specific code in the begin track process then selects either the melody piece from 1c:822b (8 words) or the placeholder beep (block address $9299) for each piece: 823B LDA $761E 823E STA $B0 8240 LDY #$00 8242 BEQ $8250 8244 LDA #$99 8246 STA $076E,Y 8249 INY 824A LDA #$92 824C STA $076E,Y 824F INY 8250 TYA 8251 CMP #$10 8253 BEQ $8269 8255 LSR $B0 8257 BCC $8244 8259 LDA $822B,Y 825C STA $076E,Y 825F INY 8260 LDA $822B,Y 8263 STA $076E,Y 8266 INY 8267 BNE $8250 8269 RTS 1c:8fd6 byte[$68?]: Note length table in frames Code to load the current length for notes: 8CAA LDA $8FD6,Y Code to limit the triangle auto-release length to 15 frames ($3c quarter-frames) when in dynamic auto-release mode: 8D73 CMP #$3C 8D75 BCC $8D79 8D77 LDA #$3C 1c:8f4c big-endian word[$43]: Key pitch table, in period register units. For square wave channels, period = 1789773 / frequency / 16 - 1 (triangle channel is 1 octave lower). Entry 1 must be 0 as it is rest. Code to load the period for a key: 8CC6 LDA $8F4D,Y ... 8CE1 LDA $8F4D,Y 8CE4 STA $0780,X 8CE7 LDA $8F4C,Y 8CEA ORA #$08 8CEC STA $0781,X 1c:8928 byte[$1f?]: Noise presets table. Data actually starts at offset 1 ($b201), and is NOT an array, as some entries overlap. The first byte should always be $10 as preset 1 is rest. +0 byte: Ctrl 1 value +1 word: Period regs value Code to play a noise preset: 8D93 LDA $8928,Y 8D96 STA NoiseVolume_400C 8D99 LDA $8929,Y 8D9C STA NoisePeriod_400E 8D9F LDA $892A,Y 8DA2 STA NoiseLength_400F Code to play a DMC preset if any: 8DA6 TYA 8DA7 AND #$C0 8DA9 CMP #$40 8DAB BEQ $8DB2 8DAD CMP #$80 8DAF BEQ $8DBC 8DB1 RTS 8DB2 LDA #$0E <- preset 1: kick drum 8DB4 STA $B1 8DB6 LDA #$07 8DB8 LDY #$00 8DBA BEQ $8DC4 8DBC LDA #$0E <- preset 2: snare drum 8DBE STA $B1 8DC0 LDA #$0F 8DC2 LDY #$02 8DC4 STA DmcLength_4013 8DC7 STY DmcAddress_4012 8DCA LDA $07F7 8DCD BNE $8DE3 8DCF LDA $B1 8DD1 STA DmcFreq_4010 8DD4 LDA #$0F 8DD6 STA ApuStatus_4015 8DD9 LDA #$00 8DDB STA DmcCounter_4011 8DDE LDA #$1F 8DE0 STA ApuStatus_4015 8DE3 RTS Volume Envelope Table 1c:8ded word[$1b]: Volume envelope table. Indices are 0-based, unlike in the set timbre commands and the following table. Envelope 1 @8e4f: 233456776554 ff Envelope 2 @8e56: 5a9888776666655555 ff Envelope 3 @8e76: 111122223333444444455555556666777888 ff Envelope 4 @8e89: f987777766655544 ff Envelope 5 @8e92: a876 ff Envelope 6 @8e98: 99 ff Envelope 7 @8e48: 235678888887 ff Envelope 8 @8e9a: dcba998887765544 ff Envelope 9 @8ea3: 2344333333333332 ff Envelope a @8e95: 7432 ff Envelope b @8eac: 7776655544433221 f0 Envelope c @8eb5: 44433332221111 f0 Envelope d @8ebd: 33332222111111 f0 Envelope e @8ec5: 222222111111 f0 Envelope f @8ecc: 1111111111110100 f0 Envelope 10 @8ed5: 998877766655544433333332222222222111111111111111 f0 Envelope 11 @8f20: 23455544333322 ff Envelope 12 @8f28: 87654321443321113221111121111111111111 ff Envelope 13 @8eee: 6555544433333333222222221111111111111111 f0 Envelope 14 @8f3c: 666542213221111121111111111111 ff Envelope 15 @8f03: fbbaaa99999998887777776666665554444443333322222222111111 f0 Envelope 16 @8e23: 7611111431 ff Envelope 17 @8e60: 111122223333444444455555556666777888765432 ff Envelope 18 @8e3f: 9876632287765311 f0 Envelope 19 @8e38: 233332222222 ff Envelope 1a @8e2d: 91919191919191919191 f0 Envelope 1b @8e29: 334566 ff Code to load an envelope address: 8B28 LDA $8DED,Y 8B2B STA $B2 8B2D LDA $8DEE,Y 8B30 STA $B3 Pitch Envelopes Pitch envelopes are difficult to describe as they're a mixture of data and code. To start with, the simple envelopes that just do vibrato, #5 with a fade in (for convenience period offsets are in decimal): Envelope 1 @8a33: | +0 +1 +1 +2 +1 +0 -1 -1 -2 -1 Envelope 5 @8a12: +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 -1 +0 +0 +0 +0 +1 +1 +0 +0 +0 -1 -1 +0 | +0 +1 +1 +2 +1 +0 -1 -1 -2 -1 Envelope 7 @8a33: | +0 +1 +1 +2 +1 +0 -1 -1 -2 -1 Envelope 2 is effectively as follows, but the loop at the end is actually hard-coded: Envelope 2 @8a3d: +0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -10 -9 -10 -11 | -10 Envelope 3 is hard-coded to -2 period units. Oddly, it checks whether the key number is < $4c/2 = $26, but then sets the offset to -2 in both cases. Envelopes 4 and 6 are simple (identical) vibrato envelopes, but hard-coded to NOT apply to key $46/2 = $23: Envelope 4 @8a06: +9 +8 +7 +6 +5 +4 +3 +2 +2 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 -1 +0 +0 +0 +0 +1 +1 | +0 +0 +0 -1 -1 +0 +0 +1 +1 +2 Envelope 6 @8a06: +9 +8 +7 +6 +5 +4 +3 +2 +2 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 -1 +0 +0 +0 +0 +1 +1 | +0 +0 +0 -1 -1 +0 +0 +1 +1 +2 The weirdness on envelopes 3, 4, and 6 are found on all games using this engine that I've investigated. The code. It actually starts at $89b4, with the pitch envelope index in the high 3 bits of $b0 and the current index into the envelope in $b2: 8977 LDA $B2 <- envelopes 4 and 6 8979 CMP #$31 897B BNE $897F 897D LDA #$27 897F TAY 8980 LDA $8A06,Y 8983 PHA 8984 LDA $07C3,X 8987 CMP #$46 8989 BNE $8990 898B PLA 898C LDA #$00 <- hard-coded +0 pitch adjustment if current key number is $46/2 = $23 898E BEQ $89EE 8990 PLA 8991 JMP $89EE 8994 LDA $B2 <- envelope 2 8996 TAY 8997 CMP #$10 8999 BCS $89A1 899B LDA $8A3D,Y 899E JMP $89F4 89A1 LDA #$F6 89A3 BNE $89F4 89A5 LDA $07C3,X <- envelope 3 89A8 CMP #$4C <- utterly pointless key number check as both paths are the same 89AA BCC $89B0 89AC LDA #$FE 89AE BNE $89F4 89B0 LDA #$FE 89B2 BNE $89F4 ... 89B4 LDA $07D1,X <- actually starts here 89B7 STA $B2 89B9 LDA $B0 89BB CMP #$20 89BD BEQ $89D3 <- envelope 1 branch 89BF CMP #$A0 89C1 BEQ $89E2 <- envelope 5 branch 89C3 CMP #$60 89C5 BEQ $89A5 <- envelope 3 branch 89C7 CMP #$40 89C9 BEQ $8994 <- envelope 2 branch 89CB CMP #$80 89CD BEQ $8977 <- envelope 4 branch 89CF CMP #$C0 89D1 BEQ $8977 <- envelope 6 branch 89D3 LDA $B2 <- envelopes 1 and 7 89D5 CMP #$0A 89D7 BNE $89DB 89D9 LDA #$00 89DB TAY 89DC LDA $8A33,Y 89DF JMP $89EE 89E2 LDA $B2 <- envelope 5 89E4 CMP #$2B 89E6 BNE $89EA 89E8 LDA #$21 89EA TAY 89EB LDA $8A12,Y 89EE PHA 89EF TYA 89F0 STA $07D1,X 89F3 PLA 89F4 PHA <- common path 89F5 LDA $07C8,X 89F8 BNE $8A04 <- don't mess with it if a sound effect is playing 89FA PLA 89FB CLC 89FC ADC $B1 89FE LDY $BE 8A00 STA Sq0Timer_4002,Y 8A03 RTS 8A04 PLA 8A05 RTS The code that determines whether a given envelope has the triangle "forever" flag set: 8D5C LDA $079C <- pitch envelope in top 3 bits 8D5F AND #$C0 8D61 BNE $8D66 8D63 TYA 8D64 BNE $8D6E 8D66 CMP #$C0 8D68 BEQ $8D63 8D6A LDA #$FF <- forever. Either bit 6 or 7 is set, but not both.